/**
 * @author phi
 * canvas を拡張
 */

(function(){ "use strict"; })();

(function(){
    var DOM = TM.DOM = TM.DOM || {}
})();


// dom をロード
TM.loadScript("dom", "dom", function(){
    
    // #pragma 的なものだと思ってもらえれば...
    if (!TM.DOM.Element) {
        setTimeout(arguments.callee, 0); return ;
    }
    
    var Editor = TM.DOM.Editor = TM.createClass({
        superClass: TM.DOM.Element,
        
        /**
         * 初期化
         */
        init: function(target) {
            // 親の初期化
            TM.DOM.Element.prototype.init.apply(this, arguments);
            // canvas かをチェック
            console.assert(this.element instanceof HTMLTextAreaElement);
        },
        
        /**
         * コマンドを実行
         */
        execCommand: function(a, b, c)
        {
            var d = this.element.ownerDocument;
            d.execCommand(a, b, c);
        },
        
        
        /**
         * 挿入
         */
        insert: function(text, start, end)
        {
            this.element.focus();
            this.prevSelection = this.element.selectionStart;
            
            if (arguments.length === 2) {
                this.element.selectionStart = this.element.selectionEnd = start;
            }
            else if (arguments.length === 3) {
                this.element.selectionStart = start;
                this.element.selectionEnd   = end;
            }
            
            // 挿入
            if (TM.venderPrefix == "webkit") {
                this.execCommand("insertText", false, text);
            }
            else if (TM.venderPrefix == "moz") {
                // TODO: firefox use
            }
        },
        
        /**
         * インデント
         */
        indent: function() {
            if (this.selection.isCursor()) {
                var line_head = this.selection.getLineHead();
                var len = this.selection.start - line_head;
                len = 4-( (len+4)%4 );
                var space = '';
                for (var i=0; i<len; ++i) space += ' ';
                this.insert(space);
            }
            else {
                
                // 複数行選択
                if (this.selection.isMultLine()) {
                    var block = this.selection.getBlock();
                    var count = 0;
                    var text = block.text.replace(/\n/g, function(){
                        ++count;
                        return "\n    ";
                    });
                    
                    var s = this.selection.start;
                    var e = this.selection.end;
                    
                    this.insert("    " + text, block.start, block.end);
                    
                    this.selection.start= s + 4;
                    this.selection.end  = e + 4 + (count*4);
                }
                // 行内選択
                else {
                    
                }
                
            }
        },
        
        /**
         * アウトデント
         */
        outdent: function()
        {
            if (this.selection.isCursor()) {
                var block = this.selection.getBlock();
                var space = block.text.slice(0, 4);
                
                if (space === "    ") {
                    var temp = block.text.slice(4);
                    if (temp == "") temp = '\0';
                    var s = this.selection.start;
                    this.insert(temp, block.start, block.end);
                    this.selection.start = this.selection.end = s-4;
                }
            }
        },
        
        /**
         * オートインデント
         */
        autoIndent: function() {
            var block = this.selection.getBlock();
            var head = this.selection.getLineHead();
            var text = this.value.slice(head, this.selection.start);
            var space = text.match(/^ +/);
            var brace_start = text.match(/\{ *$/);
            
            var insert_text = (space) ? '\n'+space : '\n';
            this.insert(insert_text);
            
            // if (brace_start) this.insert("    ");
        },
        
        /**
         * オートブラケット
         */
        autoBracket: function()
        {
            return ;
            var block = this.selection.getBlock();
            var head = this.selection.getLineHead();
            var text = this.value.slice(head, this.selection.start);
            var space = text.match(/^ +/);
            var brace_start = text.match(/\{ *$/m);
            
            if (brace_start) this.autoIndent();
        },
        
        
        /**
         *  囲む
         */
        wrap: function(start, end)
        {
            if (this.selection.isCursor()) {
                this.insert(start+end);
                this.selection.start -= end.length;
                this.selection.end = this.selection.start;
            }
            else {
                // 選択中のテキスト
                var text = this.selection.getText();
                text = start+text+end;
                this.insert(text);
            }
        },
        
        
        /**
         * コメントアウト
         */
        comment: function()
        {
            var isComment = function(line) {
                return line.match(/^ *\/\//);
            };
            
            // テキストブロックを取得
            var block = this.selection.getBlock();
            // 行分割
            var lines = block.text.split('\n');
            // 全ての行がコメントかを判定
            var comment_count = 0;
            for (var i=0; i<lines.length; ++i) {
                if ( isComment(lines[i]) ) { ++comment_count; }
            }
            
            // 全てコメントの場合コメントを外す(uncomment)
            if (lines.length == comment_count) {
                for (var i=0; i<lines.length; ++i) {
                    lines[i] = lines[i].replace(/(^ *\/\/)/, function(m){
                        return m.slice(0, -2);
                    });
                }

                var s = this.selection.start;
                var e = this.selection.end;
                this.insert( lines.join('\n'), block.start, block.end );
                this.selection.start= s - 2;
                this.selection.end  = e - lines.length*2;
            }
            // コメントアウト(comment out)
            else {
                for (var i=0; i<lines.length; ++i) {
                    lines[i] = lines[i].replace(/(^ *)/, function(m){
                        return m+"//";
                    });
                }
                
                var s = this.selection.start;
                var e = this.selection.end;
                this.insert( lines.join('\n'), block.start, block.end );
                
                this.selection.start= s + 2;
                this.selection.end  = e + lines.length*2;
            }
        },
        
        /**
         * デフォルト仕様(comment は // )
         */
        settingDefault: function()
        {
            
        },
        
        
        /**
         * emacs 仕様
         */
        settingEmacs: function()
        {
            this.key.down("Ctrl+b",  function(){ this.selection.setCursor(this.selection.start-1); return false; });
            this.key.down("Ctrl+f",  function(){ this.selection.setCursor(this.selection.start+1); return false; });
            // editor.key.down("Ctrl+p",  function(){ this.selection.setCursor(this.selection.start-1); return false; });
            // editor.key.down("Ctrl+n",  function(){ this.selection.setCursor(this.selection.start-1); return false; });
        }

    });
    
    /**
     * セレクション
     */
    var Selection = TM.createClass({
        
        /**
         * ターゲット
         */
        target  : null,
        
        
        /**
         * 初期化
         */
        init: function(target) {
            this.target = target;
        },
        
        
        /**
         * カーソルをセット
         */
        setCursor: function(start, end)
        {
            if (arguments.length == 1) {
                this.start  = start;
                this.end    = start;
            }
            else if (arguments.length == 2) {
                this.start  = start;
                this.end    = end;
            }
        },
        
        
        /**
         * カーソル?
         */
        isCursor: function() { return this.start === this.end; },
        
        /**
         * ブロック?
         */
        isBlock : function() { return this.start !== this.end; },
        
        
        /**
         * 複数行?
         */
        isMultLine: function() { return this.getText().indexOf('\n') >= 0 },
        
        
        /**
         * 選択中のテキストを取得
         */
        getText: function() {
            return this.target.value.slice(this.start, this.end);
        },
        
        /**
         * カーソル位置があるワードを取得
         */
        getWord: function() {
            return this.target.value.slice( this.getWordHead(), this.getWordTail() );
        },
        
        getWordHead: function() {
            var ch = this.target.value[this.start];
            var re_str = "";
            if (ch.search(/[ぁ-ん]/)!=-1)         { console.log("----全角ひらがな----"); re_str="[ぁ-ん]"; }
            else if (ch.search(/[ァ-ン]/)!=-1)    { console.log("----全角カタカナ----"); re_str="[ァ-ンー]"; }
            else if (ch.search(/\w/)!=-1)       { console.log("----アルファベット----"); re_str="\\w"; }
            else if (ch.search(/ /)!=-1)        { console.log("----空白文字----"); re_str=" "; }
            else if (ch.search(/\n/)!=-1)       { console.log("----改行文字----"); re_str="\\n"; }
            //else if (ch.search(/\s/)!=-1)        { console.log("----空白文字----"); re_str="\\s"; }
            else if (ch.search(/[^\w\s]/)!=-1)   { console.log("----その他----"); re_str="[^ぁ-んァ-ン\\w\\s]"; }
            
            var text = this.target.value.slice(0, this.start);
            var re = RegExp(re_str+"*$");
            // var re = new RegExp("\\w*$");
            var pos = text.search(re);
            console.log( "head: ", pos, "match: ", re_str );
            return pos;
        },
        getWordTail: function() {
            var ch = this.target.value[this.start];
            var re_str = "";
            if (ch.search(/\w/)!=-1)        { console.log("----アルファベット----"); re_str="\\W"; }
            if (ch.search(/\s/)!=-1)        { console.log("----空白文字----"); re_str="\\S"; }
            if (ch.search(/[^\w\s]/)!=-1)   { console.log("----その他----"); re_str="[\\w\\s]"; }
            
            var text = this.target.value.slice(this.start);
            var re = new RegExp(re_str);
            // var pos = text.search(/\W/);
            var pos = text.search(re);
            console.log( "tail : ", pos );
            return this.start + pos;
        },
        
        /**
         * カーソルのある行の先頭を取得
         */
        getLineHead: function() {
            var p = this.target.value.lastIndexOf('\n', this.start-1);
            return (p < 0) ? 0 : p+1;
        },
        
        
        /**
         * カーソルのある行の末尾を取得
         */
        getLineTail: function() {
            var p = this.target.value.indexOf('\n', this.end);
            return (p < 0) ? this.end : p;
        },
        
        
        /**
         * テキストブロックを取得
         */
        getBlock: function() {
            var block = {};
            block.start = this.getLineHead();
            block.end   = this.getLineTail();
            block.text  = this.target.value.slice(block.start, block.end);
            
            return block;
        },
    });
    
    Selection.prototype.accessor("start", {
        "get": function()   { return this.target.element.selectionStart; },
        "set": function(p)  { this.target.element.selectionStart = p; }
    });

    Selection.prototype.accessor("end", {
        "get": function()   { return this.target.element.selectionEnd; },
        "set": function(p)  { this.target.element.selectionEnd = p; }
    });
    
    
    Editor.prototype.getter("selection", function(){
        return this._selection|| ( this._selection = Selection(this) );
    });
    
    var getTextType = function(ch)
    {
        if      (ch.search(/[ぁ-ん]/)!=-1)    { console.log("----全角ひらがな----");    re_str="[ぁ-ん]"; }
        else if (ch.search(/[ァ-ン]/)!=-1)    { console.log("----全角カタカナ----");    re_str="[ァ-ンー]"; }
        else if (ch.search(/[a-zA-Z]/)!=-1) { console.log("----アルファベット----");   re_str="[a-zA-Z]"; }
        else if (ch.search(/\d/)!=-1)       { console.log("----数字----");        re_str="\\d"; }
        else if (ch.search(/ /)!=-1)        { console.log("----空白文字----");      re_str=" "; }
        else if (ch.search(/\n/)!=-1)       { console.log("----改行文字----");      re_str="\\n"; }
        else if (ch.search(/[^\w\s]/)!=-1)  { console.log("----その他----");       re_str="[^ぁ-んァ-ン\\w\\s]"; }
    }
    
});








